package com.erlang4j.internal.process;

import static com.erlang4j.api.Erlang4jMessageLanguage.binding;
import static com.erlang4j.api.Erlang4jMessageLanguage.state;
import static com.erlang4j.api.Erlang4jMessageLanguage.string;

import java.io.IOException;

import junit.framework.TestCase;

import com.ericsson.otp.erlang.OtpErlangPid;
import com.ericsson.otp.erlang.OtpNode;
import com.erlang4j.api.Erlang4jMessageLanguage;
import com.erlang4j.api.exceptionHandler.SysoutExceptionHandler;
import com.erlang4j.api.exceptions.Erlang4jWrappedException;
import com.erlang4j.internal.adapters.MockAdapterWithException;
import com.erlang4j.internal.basicIo.MockBasicMailBox;
import com.erlang4j.tests.Erlang4JTestHelper;

public class ProcessExceptionTest extends TestCase {

	public void testExceptions() throws IOException {
		Exception exception = new Exception();
		assertEquals(exception, checkException("basic", exception, Erlang4jWrappedException.class).getCause());
		assertEquals(exception, checkException("swing", exception, Erlang4jWrappedException.class).getCause());

		RuntimeException runtimeException = new RuntimeException() {
		};
		checkException("basic", runtimeException, runtimeException.getClass());
		checkException("swing", runtimeException, runtimeException.getClass());

	}

	private <T extends Exception> T checkException(final String atom, Exception runtimeException, Class<T> clazz) throws IOException {
		OtpErlangPid self = new OtpNode("somevalue").createPid();
		MockBasicMailBox mockBasicMailBox = new MockBasicMailBox(self, string("receive"));
		MockAdapterWithException adapter1 = new MockAdapterWithException("basic", runtimeException);
		MockAdapterWithException adapter2 = new MockAdapterWithException("swing", runtimeException);
		final StateMachine messageProcessor = new StateMachine(mockBasicMailBox, //
				new SysoutExceptionHandler(), binding("this is ignored", "in this test"), //
				state(null, adapter1, adapter2));
		T actual = Erlang4JTestHelper.assertThrows(clazz, new Runnable() {
			public void run() {
				messageProcessor.process(Erlang4jMessageLanguage.atom(atom));
			}
		});
		return actual;

	}

}
